﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace SharpSoft.WPF.Controls
{
    using System.Windows;
    using System.Windows.Controls;
    using System.Windows.Media;
    using System.Windows.Media.Animation;
    using System.Windows.Shapes;

    /// <summary>
    /// 带有展开动画效果的指示线。
    /// 
    /// </summary>
    public class IndicatrixLine : Control
    {
        static IndicatrixLine()
        {
            DefaultStyleKeyProperty.OverrideMetadata(typeof(IndicatrixLine), new FrameworkPropertyMetadata(typeof(IndicatrixLine)));
        }
        public IndicatrixLine()
        {

            this.Loaded += IndicatrixLine_Loaded;
        }

        private void IndicatrixLine_Loaded(object sender, RoutedEventArgs e)
        {


        }

        public override void OnApplyTemplate()
        {
            base.OnApplyTemplate();
            linePath = (Path)this.Template.FindName("linePath", this);
            pathGeometry = new PathGeometry() { };
            pf = new PathFigure() { StartPoint = new Point(0, 0), IsClosed = false };
            line1 = new LineSegment(new Point(1, 1), true);
            line2 = new LineSegment(new Point(2, 2), true);
            pf.Segments.Add(line1);
            pf.Segments.Add(line2);
            pathGeometry.Figures.Add(pf);
            linePath.Data = this.pathGeometry;
            recalcPath();
        }
        Path linePath; PathFigure pf;
        PathGeometry pathGeometry;
        LineSegment line1, line2;


        /// <summary>
        /// 获取或设置控件中心在<see cref="Canvas"/>中的位置
        /// </summary>
        public Point CenterPosition
        {
            get
            {
                var x = Canvas.GetLeft(this);
                var y = Canvas.GetTop(this);
                if (double.IsNaN(x))
                {
                    x = 0d;
                }
                if (double.IsNaN(y))
                {
                    y = 0d;
                }
                return new Point(x + this.Width / 2, y + this.Height / 2);

            }
            set { SetValue(CenterPositionProperty, value); }
        }

        public static readonly DependencyProperty CenterPositionProperty =
            DependencyProperty.Register("CenterPosition", typeof(Point), typeof(IndicatrixLine), new PropertyMetadata(default(Point)));




        /// <summary>
        /// 起点（圆圈的中心位置）
        /// </summary>
        public Point StartPoint
        {
            get { return (Point)GetValue(StartPointProperty); }
            private set { SetValue(StartPointPropertyKey, value); }
        }
        private static DependencyPropertyKey StartPointPropertyKey = DependencyProperty.RegisterReadOnly("StartPoint", typeof(Point), typeof(IndicatrixLine), new PropertyMetadata(default(Point)));
        public static DependencyProperty StartPointProperty = StartPointPropertyKey.DependencyProperty;


        /// <summary>
        /// 终点（坐标相对于此控件的左上角）
        /// </summary>
        public Point EndPoint
        {
            get { return (Point)GetValue(EndPointProperty); }
            set { SetValue(EndPointProperty, value); }
        }

        public static readonly DependencyProperty EndPointProperty =
            DependencyProperty.Register("EndPoint", typeof(Point), typeof(IndicatrixLine), new PropertyMetadata(default(Point)));
        /// <summary>
        /// 转折位置的比例(从起始位置到终点位置)
        /// </summary>
        public double BendRatio
        {
            get { return (double)GetValue(BendRatioProperty); }
            set { SetValue(BendRatioProperty, value); }
        }

        public static readonly DependencyProperty BendRatioProperty =
            DependencyProperty.Register("BendRatio", typeof(double), typeof(IndicatrixLine), new PropertyMetadata(0.5d));



        /// <summary>
        /// 线条宽度
        /// </summary>
        public double StrokeThickness
        {
            get { return (double)GetValue(StrokeThicknessProperty); }
            set { SetValue(StrokeThicknessProperty, value); }
        }

        public static readonly DependencyProperty StrokeThicknessProperty =
            DependencyProperty.Register("StrokeThickness", typeof(double), typeof(IndicatrixLine), new PropertyMetadata(1d));


        protected override void OnPropertyChanged(DependencyPropertyChangedEventArgs e)
        {
            base.OnPropertyChanged(e);
            if (e.Property == EndPointProperty || e.Property == BendRatioProperty || e.Property == StartPointProperty)
            {
                recalcPath();
            }
            else if (e.Property == WidthProperty || e.Property == HeightProperty || e.Property == CenterPositionProperty)
            {
                this.StartPoint = new Point(this.Width / 2, this.Height / 2);
                var cp = (Point)this.GetValue(CenterPositionProperty);
                var x = cp.X - this.Width / 2;
                var y = cp.Y - this.Height / 2;
                Canvas.SetLeft(this, x);
                Canvas.SetTop(this, y);
            }
            else if (e.Property == StrokeThicknessProperty)
            {
            }
            else if (e.Property == ForegroundProperty)
            {
            }
        }

        /// <summary>
        /// 播放展开动画
        /// </summary>
        public void AnimationOpen(TimeSpan dur, Action action = null)
        {
            var sb = linePath.CreateShapeDrawAnimation(dur, false);
            sb.DecelerationRatio = 0.5d;
            sb.AccelerationRatio = 0.5d;
            sb.Begin();
            if (action != null)
            {
                sb.Completed += (s, e) => { action.Invoke(); };
            }
        }
        /// <summary>
        /// 播放收缩动画
        /// </summary>
        public void AnimationClose(TimeSpan dur, Action action = null)
        {
            var sb = linePath.CreateShapeDrawAnimation(dur, true);
            sb.DecelerationRatio = 0.5d;
            sb.AccelerationRatio = 0.5d;
            sb.Begin();
            if (action != null)
            {
                sb.Completed += (s, e) => { action.Invoke(); };
            }
        }

        /// <summary>
        /// 重新计算线条的参数
        /// </summary>
        private void recalcPath()
        {
            if (this.linePath == null)
            {
                return;
            }
            var ratio = this.BendRatio;
            var sp = this.StartPoint;
            var ep = this.EndPoint;

            pf.StartPoint = sp;
            var p = new Point((ep.X - sp.X) * ratio + sp.X, sp.Y);
            line1.Point = p;
            line2.Point = ep;
            this.InvalidateVisual();
        }

        protected override void OnRender(DrawingContext dc)
        {
            base.OnRender(dc);

        }
    }
}